﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

using MiniTwitter.Extensions;

namespace MiniTwitter.Net.Twitter
{
    [Serializable]
    [XmlRoot("status")]
    public class Status : PropertyChangedBase, ITwitterItem
    {
        private DateTime createdAt;

        [XmlIgnore]
        public DateTime CreatedAt
        {
            get { return createdAt; }
            set
            {
                if (createdAt != value)
                {
                    createdAt = value;
                    OnPropertyChanged("CreatedAt");
                    this.UpdateRelativeTime();
                }
            }
        }

        private string createdAtInternal;

        [XmlElement("created_at")]
        public string CreatedAtInternal
        {
            get { return createdAtInternal; }
            set
            {
                if (createdAtInternal != value)
                {
                    if (!value.IsNullOrEmpty())
                    {
                        createdAtInternal = value;
                        CreatedAt = DateTime.ParseExact(createdAtInternal, "ddd MMM dd HH:mm:ss zzzz yyyy", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowWhiteSpaces);
                    }
                }
            }
		}

		private string relativeTime;

        [XmlIgnore]
        public string RelativeTime
        {
            get { return relativeTime; }
            set
            {
                if (relativeTime != value)
                {
                    relativeTime = value;
                    OnPropertyChanged("RelativeTime");
                }
            }
        }

        private long id;

        [XmlElement("id")]
        public long ID
        {
            get { return id; }
            set
            {
                if (id != value)
                {
                    id = value;
                    OnPropertyChanged("ID");
                }
            }
        }

        private string text;

        [XmlElement("text")]
        public string Text
        {
            get { return text; }
            set
            {
                if (text != value)
                {
                    text = TwitterClient.Unescape(value);
                    OnPropertyChanged("Text");
                }
            }
        }

        private string source;

        [XmlElement("source")]
        public string Source
        {
            get { return source; }
            set
            {
                if (source != value)
                {
                    if (!value.IsNullOrEmpty())
                    {
                        source = Regex.Replace(value, @"<(.|\n)*?>", string.Empty);
                        OnPropertyChanged("Source");
                    }
                }
            }
        }

        private bool favorited;

        [XmlElement("favorited")]
        public bool Favorited
        {
            get { return favorited; }
            set
            {
                if (favorited != value)
                {
                    favorited = value;
                    OnPropertyChanged("Favorited");
                }
            }
        }

        private long inReplyToStatusID;

        [XmlIgnore]
        public long InReplyToStatusID
        {
            get { return inReplyToStatusID; }
            set
            {
                if (inReplyToStatusID != value)
                {
                    inReplyToStatusID = value;
                    OnPropertyChanged("InReplyToStatusID");
                }
            }
        }

        private string inReplyToStatusIDInternal;

        [XmlElement("in_reply_to_status_id", IsNullable = true)]
        public string InReplyToStatusIDInternal
        {
            get { return inReplyToStatusIDInternal; }
            set
            {
                if (inReplyToStatusIDInternal != value)
                {
                    inReplyToStatusIDInternal = value;
                    if (!inReplyToStatusIDInternal.IsNullOrEmpty())
                    {
                        InReplyToStatusID = long.Parse(inReplyToStatusIDInternal);
                    }
                }
            }
        }

        private long inReplyToUserID;

        [XmlIgnore]
        public long InReplyToUserID
        {
            get { return inReplyToUserID; }
            set
            {
                if (inReplyToUserID != value)
                {
                    inReplyToUserID = value;
                    OnPropertyChanged("InReplyToUserID");
                }
            }
        }

        private string inReplyToUserIDInternal;

        [XmlElement("in_reply_to_user_id", IsNullable = true)]
        public string InReplyToUserIDInternal
        {
            get { return inReplyToUserIDInternal; }
            set
            {
                if (inReplyToUserIDInternal != value)
                {
                    inReplyToUserIDInternal = value;
                    if (!inReplyToUserIDInternal.IsNullOrEmpty())
                    {
                        InReplyToUserID = long.Parse(inReplyToUserIDInternal);
                    }
                }
            }
        }

        private string inReplyToScreenName;

        [XmlElement("in_reply_to_screen_name", IsNullable = true)]
        public string InReplyToScreenName
        {
            get { return inReplyToScreenName; }
            set
            {
                if (inReplyToScreenName != value)
                {
                    inReplyToScreenName = value;
                    OnPropertyChanged("InReplyToScreenName");
                }
            }
        }

        private User sender;

        [XmlElement("user")]
        public User Sender
        {
            get { return sender; }
            set
            {
                if (sender != value)
                {
                    sender = value;
                    OnPropertyChanged("Sender");
                }
            }
        }

        private User recipient;

        [XmlIgnore]
        public User Recipient
        {
            get { return recipient; }
            set
            {
                if (recipient != value)
                {
                    recipient = value;
                    OnPropertyChanged("Recipient");
                }
            }
        }

        public bool IsAuthor { get; set; }

        private bool isNewest;

        [XmlIgnore]
        public bool IsNewest
        {
            get { return isNewest; }
            set
            {
                if (isNewest != value)
                {
                    isNewest = value;
                    OnPropertyChanged("IsNewest");
                }
            }
        }

        [XmlIgnore]
        public bool IsReply
        {
            get { return InReplyToStatusID != 0; }
        }

        [XmlIgnore]
        public bool IsMessage
        {
            get { return false; }
        }

        public bool Equals(ITwitterItem other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            return (this.ID == other.ID);
        }

        public override int GetHashCode()
        {
            return (int)this.ID;
        }
    }
}
